<script setup lang='ts'>
import type { OptionsType, PlusForm, PlusFormGroupRow } from 'plus-pro-components'

import {
    useAcceptOrRejectPayout,
    useAcceptOrReturnReceive,
    useAddRequestPayout,
    useConfirmPayout,
    useGetEnterpriseBankAccountOptions,
    useGetRequestPayoutDetail,
    useRecallPayout,
    useResubmitRequestPayout,
} from '@fl/api/supplier'
import { FlUpload, ReasonDialog, SubmitBtn } from '@fl/components'
import { useMessage } from '@fl/hooks/web/use-message'
import { jsonToArray } from '@fl/utils/fn'
import { treeFindLabel } from '@fl/utils/tree'
import { cloneDeep } from 'lodash-es'

import { REQUEST_STATUS } from './constant'

const props = defineProps<{
    businessType: 'addRequest' | 'payDetail' | 'requestDetail' | 'resubmit' | undefined
    contractDetailData?: {
        agreementId: string
        agreementName: string
        contractPrice: number
        totalAmountInvoiced: number
        totalAmountPaid: number
        totalAmountReceived: number
        totalInvoiceReceived: number
    }
}>()

const route = useRoute()
const { createConfirmModal } = useMessage()

const id = defineModel<string>('id', { required: true })
const visible = defineModel<boolean>('visible', { required: true })

const initialState = { invoiceAttachment: [], paymentAttachment: [] } as any
const state = ref(cloneDeep(initialState))

const showReason = ref<boolean>(false)
const isReasonDialogLoading = ref<boolean>(false)
const reasonDialogTitleMap = {
    payDetail: '驳回',
    requestDetail: '退回',
}

const isDetail = computed(() => ['payDetail', 'requestDetail'].includes(props.businessType!))
const isAddOrResubmit = computed(() => ['addRequest', 'resubmit'].includes(props.businessType!))
const isPaying = computed(() => props.businessType === 'payDetail'
    && [REQUEST_STATUS.ACCEPTED, REQUEST_STATUS.RECALLED, REQUEST_STATUS.RETURNED].includes(state.value.requestStatus))
const requestId = computed(() => (isAddOrResubmit.value || isDetail.value) ? id.value : '')
const isSupplier = computed(() => route.path.includes('supplier-pages'))

const { data: enterpriseBankAccountOptionsData, isLoading: isGetEnterpriseBankAccountOptionsLoading } = useGetEnterpriseBankAccountOptions(isAddOrResubmit)
const { isPending: isAddRequestPayoutPending, mutate: addRequestPayout } = useAddRequestPayout()
const { data: requestPayoutDetailData, isLoading: isGetRequestPayoutDetailLoading } = useGetRequestPayoutDetail(requestId)
const { isPending: isConfirmPayoutPending, mutate: confirmPayout } = useConfirmPayout()
const { isPending: isAcceptOrRejectPayoutPending, mutate: acceptOrRejectPayout } = useAcceptOrRejectPayout()
const { isPending: isRecallPayoutPending, mutate: recallPayout } = useRecallPayout()
const { isPending: isAcceptOrReturnReceivePending, mutate: acceptOrReturnReceive } = useAcceptOrReturnReceive()
const { isPending: isResubmitRequestPayoutPending, mutate: resubmitRequestPayout } = useResubmitRequestPayout()

// #region Form
const formRef = ref()
const isFormLoading = computed(() => isGetEnterpriseBankAccountOptionsLoading.value || isGetRequestPayoutDetailLoading.value)
const isSubmitLoading = computed(() =>
    isAddRequestPayoutPending.value
    || isConfirmPayoutPending.value
    || isAcceptOrRejectPayoutPending.value
    || isRecallPayoutPending.value
    || isAcceptOrReturnReceivePending.value
    || isResubmitRequestPayoutPending.value)

const group: ComputedRef<PlusFormGroupRow[]> = computed(() => [
    {
        columns: [
            {
                colProps: {
                    span: 12,
                },
                fieldProps: {
                    disabled: true,
                },
                label: '合同名称',
                prop: 'agreementName',
                valueType: isDetail.value ? 'text' : 'copy',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '合同金额',
                prop: 'contractPrice',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '已收款总金额',
                prop: 'totalAmountReceived',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '已开票总金额',
                prop: 'totalAmountInvoiced',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '本次申请请款金额',
                prop: 'requestAmount',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '本次开票金额',
                prop: 'invoiceAmount',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '收款账号',
                options: enterpriseBankAccountOptionsData as OptionsType,
                prop: isDetail.value ? 'paymentAccount' : 'paymentAccountId',
                valueType: isDetail.value ? 'text' : 'select',
            },
            {
                colProps: {
                    span: 24,
                },
                label: '附件',
                prop: 'invoiceAttachment',
            },
        ],
        title: '请款信息',
    },
    {
        columns: [
            {
                colProps: {
                    span: 12,
                },
                hideInForm: computed(() => !isPaying.value),
                label: '已付款总金额',
                prop: 'totalAmountPaid',
            },
            {
                colProps: {
                    span: 12,
                },
                hideInForm: computed(() => !isPaying.value),
                label: '已收票总金额',
                prop: 'totalInvoiceReceived',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '本次实付金额',
                prop: 'actualPaidAmount',
            },
            {
                colProps: {
                    span: 12,
                },
                label: '本次收票金额',
                prop: 'actualInvoiceAmount',
            },
            {
                colProps: {
                    span: 12,
                },
                hideInForm: computed(() => isPaying.value),
                label: '操作时间',
                prop: 'payTime',
                valueType: 'text',
            },
            {
                colProps: {
                    span: 24,
                },
                label: '附件',
                prop: 'paymentAttachment',
            },
        ],
        hideInGroup: computed(() => isAddOrResubmit.value
        || [REQUEST_STATUS.APPLYING, REQUEST_STATUS.REJECTED].includes(state.value.requestStatus)
        || (isSupplier.value && state.value.requestStatus === REQUEST_STATUS.ACCEPTED)),
        title: '付款信息',
    },
])

const rules = {
    actualInvoiceAmount: [
        {
            required: false,
            trigger: 'change',
            validator: (_rule: any, value: any, callback: any) => {
                if (value && Number(value) <= 0) {
                    callback(new Error('收票金额必须大于0'))
                }
                else {
                    callback()
                }
            },
        },
    ],
    actualPaidAmount: [
        {
            message: '请输入本次实付金额',
            required: true,
            trigger: 'change',
        },
        {
            required: true,
            trigger: 'change',
            validator: (_rule: any, value: any, callback: any) => {
                if (Number(value) <= 0) {
                    callback(new Error('实付金额必须大于0'))
                }
                else {
                    callback()
                }
            },
        },
    ],
    invoiceAmount: [
        {
            required: false,
            trigger: 'change',
            validator: (_rule: any, value: any, callback: any) => {
                if (value && Number(value) <= 0) {
                    callback(new Error('开票金额必须大于0'))
                }
                else {
                    callback()
                }
            },
        },
    ],
    paymentAccountId: [
        {
            message: '请选择收款账号',
            required: true,
            trigger: 'change',
        },
    ],
    requestAmount: [
        {
            message: '请输入本次申请请款金额',
            required: true,
            trigger: 'change',
        },
        {
            required: true,
            trigger: 'change',
            validator: (_rule: any, value: any, callback: any) => {
                if (Number(value) <= 0) {
                    callback(new Error('请款金额必须大于0'))
                }
                else {
                    callback()
                }
            },
        },
    ],
}

function submit() {
    const params = {
        ...state.value,
        invoiceAttachment: JSON.stringify(state.value.invoiceAttachment),
        paymentAccount: treeFindLabel({ targetValue: state.value.paymentAccountId, treeData: enterpriseBankAccountOptionsData.value }),
    }

    const func = props.businessType === 'resubmit' ? resubmitRequestPayout : addRequestPayout
    func(params, {
        onSuccess() {
            ElMessage.success('操作成功')
            cancel()
        },
    })
}
// #endregion

// #region UI Listener
function cancel() {
    visible.value = false
}

function closed() {
    if (isDetail.value) {
        id.value = ''
    }
    else {
        state.value = cloneDeep(initialState)
        formRef.value.formInstance.resetFields()
    }
}

function onSubmitRequestBtnClick() {
    formRef.value.handleSubmit()
}

function onReturnReceiveBtnClick() {
    showReason.value = true
}

function onConfirmReceiveBtnClick() {
    const params = {
        auditPayType: 1,
        id: state.value.id,
    }

    acceptOrReturnReceive(params, {
        onSuccess() {
            ElMessage.success('操作成功')
            cancel()
        },
    })
}

function onRejectRequestBtnClick() {
    showReason.value = true
}

function onInputReasonConfirm(value: { reason: string }) {
    if (props.businessType === 'requestDetail') {
        const params = {
            auditPayType: 2,
            id: state.value.id,
            returnReason: value.reason,
        }

        acceptOrReturnReceive(params, {
            onError() {
                isReasonDialogLoading.value = false
            },
            onSuccess() {
                isReasonDialogLoading.value = false
                ElMessage.success('操作成功')
                cancel()
            },
        })
    }
    else if (props.businessType === 'payDetail') {
        const params = {
            auditType: 2,
            id: state.value.id,
            rejectReason: value.reason,
        }

        acceptOrRejectPayout(params, {
            onError() {
                isReasonDialogLoading.value = false
            },
            onSuccess() {
                isReasonDialogLoading.value = false
                ElMessage.success('操作成功')
                cancel()
            },
        })
    }
}

function onRecallBtnClick() {
    createConfirmModal({
        content: '确定要撤回付款吗？',
        onSuccess: () => {
            recallPayout(state.value.id, {
                onSuccess() {
                    ElMessage.success('操作成功')
                    cancel()
                },
            })
        },
        title: '提示',
    })
}

function onAcceptBtnClick() {
    const params = {
        auditType: 1,
        id: state.value.id,
    }

    acceptOrRejectPayout(params, {
        onSuccess() {
            ElMessage.success('操作成功')
            cancel()
        },
    })
}

async function onConfirmPayBtnClick() {
    try {
        await formRef.value.formInstance.validate()

        const params = {
            actualInvoiceAmount: state.value.actualInvoiceAmount,
            actualPaidAmount: state.value.actualPaidAmount,
            id: state.value.id,
            paymentAttachment: JSON.stringify(state.value.paymentAttachment),
        }

        confirmPayout(params, {
            onSuccess() {
                ElMessage.success('操作成功')
                cancel()
            },
        })
    }
    catch (error) {
        console.log(error)
    }
}
// #endregion

watchEffect(() => {
    Object.assign(state.value, {
        agreementName: props.contractDetailData?.agreementName,
        contractId: props.contractDetailData?.agreementId,
        contractPrice: props.contractDetailData?.contractPrice,
        totalAmountInvoiced: props.contractDetailData?.totalAmountInvoiced || 0,
        totalAmountPaid: props.contractDetailData?.totalAmountPaid || 0,
        totalAmountReceived: props.contractDetailData?.totalAmountReceived || 0,
        totalInvoiceReceived: props.contractDetailData?.totalInvoiceReceived || 0,
    })
    if ((props.businessType === 'resubmit' || isDetail.value) && requestPayoutDetailData.value) {
        const data = cloneDeep(requestPayoutDetailData.value)
        const invoiceAttachment = jsonToArray(data.invoiceAttachment)
        const paymentAttachment = jsonToArray(data.paymentAttachment)

        Object.assign(state.value, data, {
            actualInvoiceAmount: isPaying.value ? undefined : (data.actualInvoiceAmount || 0),
            actualPaidAmount: isPaying.value ? undefined : (data.actualPaidAmount || 0),
            invoiceAttachment,
            paymentAttachment,
        })
    }
    else if (enterpriseBankAccountOptionsData.value) {
        Object.assign(state.value, {
            paymentAccountId: enterpriseBankAccountOptionsData.value.find((item: any) => item.isDefault)?.value,
        })
    }
})
</script>

<template>
    <PlusDialog v-model="visible"
                :title="businessType === 'payDetail' ? '请款详情' : '请款申请'"
                width="1200"
                close-on-press-escape
                @cancel="cancel"
                @closed="closed"
    >
        <el-skeleton v-if="isFormLoading"
                     animated
        />

        <PlusForm v-else
                  ref="formRef"
                  v-model="state"
                  :group="group"
                  :label-width="150"
                  :rules="rules"
                  :has-footer="false"
                  :row-props="{ gutter: 40 }"
                  @submit="submit"
        >
            <template #plus-field-contractPrice>
                <template v-if="isDetail">
                    {{ state.contractPrice }}元
                </template>

                <template v-else>
                    <div class="text-[12px] -mt-32">
                        注：合同金额为签订总金额
                    </div>

                    <el-input v-model="state.contractPrice"
                              type="number"
                              placeholder="请输入合同金额"
                              disabled
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-totalAmountReceived>
                <template v-if="isDetail">
                    {{ state.totalAmountReceived }}元
                </template>

                <template v-else>
                    <div class="text-[12px] -mt-32">
                        注：已收款总金额为采购商已付款凭证合计金额
                    </div>

                    <el-input v-model="state.totalAmountReceived"
                              type="number"
                              placeholder="请输入已收款总金额"
                              disabled
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-totalAmountInvoiced>
                <template v-if="isDetail">
                    {{ state.totalAmountInvoiced }}元
                </template>

                <template v-else>
                    <div class="text-[12px] -mt-32">
                        注：已开票总金额为供应商已开票的合计金额
                    </div>

                    <el-input v-model="state.totalAmountInvoiced"
                              type="number"
                              placeholder="请输入已开票总金额"
                              disabled
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-requestAmount>
                <template v-if="isDetail">
                    {{ state.requestAmount }}元
                </template>

                <template v-else>
                    <el-input v-model="state.requestAmount"
                              type="number"
                              placeholder="请输入本次申请请款金额"
                              @change="(value: string | number) => { state.requestAmount = Math.floor(Number(value) * 100) / 100 }"
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-invoiceAmount>
                <template v-if="isDetail">
                    {{ state.invoiceAmount ? `${state.invoiceAmount}元` : '--' }}
                </template>

                <template v-else>
                    <el-input v-model="state.invoiceAmount"
                              type="number"
                              placeholder="请输入本次开票金额"
                              @change="(value: string | number) => { state.invoiceAmount = Math.floor(Number(value) * 100) / 100 }"
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-invoiceAttachment>
                <FlUpload v-model="state.invoiceAttachment"
                          tips
                          accept=".pdf,.jpg,.jpeg,.png"
                          list-type="text"
                          :disabled="isDetail"
                          :limit="20"
                />
            </template>

            <template #plus-field-totalAmountPaid>
                <div class="text-[12px] -mt-32">
                    注：已付款总金额为采购商已付款凭证合计金额
                </div>

                <el-input v-model="state.totalAmountPaid"
                          type="number"
                          placeholder="请输入已付款总金额"
                          disabled
                >
                    <template #append>
                        <span>元</span>
                    </template>
                </el-input>
            </template>

            <template #plus-field-totalInvoiceReceived>
                <div class="text-[12px] -mt-32">
                    注：已收票总金额为采购商收到票据合计金额
                </div>

                <el-input v-model="state.totalInvoiceReceived"
                          type="number"
                          placeholder="请输入已收票总金额"
                          disabled
                >
                    <template #append>
                        <span>元</span>
                    </template>
                </el-input>
            </template>

            <template #plus-field-actualPaidAmount>
                <template v-if="!isPaying">
                    {{ state.actualPaidAmount }}元
                </template>

                <template v-else>
                    <el-input v-model="state.actualPaidAmount"
                              type="number"
                              placeholder="请输入本次实付金额"
                              @change="(value: string | number) => { state.actualPaidAmount = Math.floor(Number(value) * 100) / 100 }"
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-actualInvoiceAmount>
                <template v-if="!isPaying">
                    {{ state.actualInvoiceAmount ? `${state.actualInvoiceAmount}元` : '--' }}
                </template>

                <template v-else>
                    <el-input v-model="state.actualInvoiceAmount"
                              type="number"
                              placeholder="请输入本次收票金额"
                              @change="(value: string | number) => { state.actualInvoiceAmount = Math.floor(Number(value) * 100) / 100 }"
                    >
                        <template #append>
                            <span>元</span>
                        </template>
                    </el-input>
                </template>
            </template>

            <template #plus-field-paymentAttachment>
                <FlUpload v-model="state.paymentAttachment"
                          tips
                          accept=".pdf,.jpg,.jpeg,.png"
                          list-type="text"
                          :disabled="!isPaying"
                          :limit="20"
                />
            </template>
        </PlusForm>

        <template #footer>
            <div class="mx-auto">
                <el-button @click="cancel">
                    取消
                </el-button>

                <SubmitBtn v-if="isAddOrResubmit"
                           type="primary"
                           :loading="isSubmitLoading"
                           @click="onSubmitRequestBtnClick"
                >
                    提交
                </SubmitBtn>

                <SubmitBtn v-if="businessType === 'requestDetail' && state.requestStatus === REQUEST_STATUS.PAID"
                           :loading="isSubmitLoading"
                           type="primary"
                           @click="onReturnReceiveBtnClick"
                >
                    退回
                </SubmitBtn>

                <SubmitBtn v-if="businessType === 'requestDetail' && state.requestStatus === REQUEST_STATUS.PAID"
                           type="primary"
                           :loading="isSubmitLoading"
                           @click="onConfirmReceiveBtnClick"
                >
                    确认收款
                </SubmitBtn>

                <SubmitBtn v-if="businessType === 'payDetail' && state.requestStatus === REQUEST_STATUS.APPLYING"
                           :loading="isSubmitLoading"
                           @click="onRejectRequestBtnClick"
                >
                    驳回
                </SubmitBtn>

                <SubmitBtn v-if="businessType === 'payDetail' && state.requestStatus === REQUEST_STATUS.APPLYING"
                           type="primary"
                           :loading="isSubmitLoading"
                           @click="onAcceptBtnClick"
                >
                    确认接收
                </SubmitBtn>

                <SubmitBtn v-if="businessType === 'payDetail' && state.requestStatus === REQUEST_STATUS.PAID"
                           :loading="isSubmitLoading"
                           type="primary"
                           @click="onRecallBtnClick"
                >
                    撤回
                </SubmitBtn>

                <SubmitBtn v-if="isPaying"
                           type="primary"
                           :loading="isSubmitLoading"
                           @click="onConfirmPayBtnClick"
                >
                    确认付款
                </SubmitBtn>
            </div>
        </template>
    </PlusDialog>

    <ReasonDialog v-model:visible="showReason"
                  v-model:loading="isReasonDialogLoading"
                  :title="reasonDialogTitleMap[businessType!]"
                  mode="input"
                  @confirm="onInputReasonConfirm"
    />
</template>

<style lang="scss" scoped>
:deep(.el-form-item--default) {
    margin-bottom: 0;
    margin-top: 32px;
}
</style>
